#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Datetime: 2020/11/27 10:29
# @Author  : thinkive_cfy_ide_3
# @Site    :
# @File    : product_ret_decomposition.py
# @Software: PyCharm

"""
组合持仓产品收益分解：分解到产品，不同于asset_ret_decomposition是对底层资产收益率分解
"""


import pandas as pd
from quant_researcher.quant.datasource_fetch.portfolio_api.portfolio_tool import get_portfolio_hold_related_info, get_portfolio_nav_related_info


def performance_contri(portfolio_df, portfolio_nav):
    """

    :param pd.DataFrame portfolio_df:组合持仓数据，必须包含持仓区间内所有交易的以下相关信息：
                    date：持仓日期,
                    code：持仓资产代码,
                    asset_value: 持仓资产期末市值，
                    bonus_value：现金分红，
                    buy_value：当日申购金额，
                    sell_value：当日赎回金额，
    :param pd.DataFrame portfolio_nav: 账户净值数据
                    必须包含的信息有：
                    date: 日期，
                    nav：组合净值，
    :return:
    """
    df = portfolio_df
    mask = df['asset_value'] != 0
    df['asset_value_1'] = df.groupby(['code'])['asset_value'].shift()
    df['asset_end_date_profit_value'] = df['asset_value']+df['sell_value'] + df['bonus_value'] - df['buy_value'] - df['asset_value_1']
    df['asset_end_date_return'] = df['asset_end_date_profit_value'] / df['asset_value_1']
    df['asset_value_begin'] = df.groupby(['code'])['asset_value'].transform(lambda x: x.iloc[0])
    df['asset_period_sell_value'] = df.groupby(['code'])['sell_value'].transform(sum)
    df['asset_period_buy_value'] = df.groupby(['code'])['buy_value'].transform(sum)
    df['asset_period_bonus_value'] = df.groupby(['code'])['bonus_value'].transform(sum)
    df['asset_period_profit_value'] = df['asset_value']+df['asset_period_sell_value']+df['asset_period_bonus_value'] - df['asset_period_buy_value'] - df['asset_value_begin']
    df['asset_period_return'] = df['asset_period_profit_value'] / df['asset_value_begin']
    df['asset_period_profit_value'] = df['asset_period_profit_value'].where(mask)
    df['asset_period_profit_value'] = df.groupby('code')['asset_period_profit_value'].ffill()
    df['asset_period_return'] = df['asset_period_return'].where(mask)
    df['asset_period_return'] = df.groupby('code')['asset_period_return'].ffill()
    df['portfolio_end_date_profit_value'] = df.groupby('date')['asset_end_date_profit_value'].transform(sum)
    df['portfolio_end_date_balance'] = df.groupby('date')['asset_value'].transform(sum)
    df['portfolio_end_date_return'] = df['portfolio_end_date_profit_value'] / df['portfolio_end_date_balance']
    df['portfolio_period_balance_begin'] = df['portfolio_end_date_balance'][0]
    df['portfolio_period_profit_value'] = df['portfolio_end_date_balance']+df['sell_value'].sum() +\
                                          df['bonus_value'].sum() - df['buy_value'].sum() - df['portfolio_period_balance_begin']
    df['portfolio_period_return'] = portfolio_nav['nav'].iloc[-1] / portfolio_nav['nav'].iloc[0] - 1
    # df['portfolio_period_return'] = df['portfolio_period_profit_value'] / df['portfolio_period_balance_begin']
    df['asset_contribution'] = df['asset_period_profit_value'] / df['portfolio_period_profit_value']
    result = df[df['date']==df['date'].max()]
    # fund_result = result[['code', 'fund_name', 'asset_value',
    #                      'net_value', 'total_qty', 'asset_end_date_profit_value',
    #                      'asset_period_profit_value', 'asset_period_return', 'asset_contribution']]
    # portfolio_result = result[['portfolio_end_date_balance','portfolio_end_date_profit_value','portfolio_period_profit_value','portfolio_period_return']].iloc[0]
    return result


if __name__ == '__main__':
    start_date = '2019-09-01'
    end_date = '2020-01-01'
    portfolio_id = 1076
    start = start_date.replace('-','')
    end = end_date.replace('-','')
    portfolio_df = get_portfolio_hold_related_info(portfolio_id, start, end)
    portfolio_df = portfolio_df[['backup_date','fund_code', 'fund_name', 'bonus_balance','fund_balance', 'buy_balance','net_value', 'sell_balance', 'total_qty']]
    portfolio_df.columns = ['date','code', 'fund_name', 'bonus_value','asset_value', 'buy_value','net_value', 'sell_value', 'total_qty']
    nav_p = get_portfolio_nav_related_info(portfolio_id, start, end)
    nav_p = nav_p[['trade_date', 'account_net_value']]
    nav_p.columns = ['date', 'nav']
    fund, portfolio = performance_contri(portfolio_df, nav_p)


